package com.authine.cloudpivot.ext.applicationservice.authority;

import com.alibaba.cola.dto.RequestContext;
import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.ext.applicationservice.organization.UserApi;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.dto.MenuData;
import com.authine.cloudpivot.ext.dto.system.ResourceDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.enums.system.ResourceTypeEnum;
import com.authine.cloudpivot.ext.utils.BoServiceUtils;
import com.authine.common.util.ObjectMapperUtils;
import com.authine.mvp.app.launcher.dto.bo.query.expression.Operator;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import io.swagger.v3.oas.annotations.Operation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.util.StringUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

/**
 * @ClassName UserMenuService
 * @Description: 用户导航菜单服务
 * @Author fj
 * @Date 2021/9/26
 * @Version V1.0
 **/
@Path("UserMenuService")
@Slf4j
public class UserMenuService {
    private static final UserApi user = new UserApi();

    /**
     * 获取当前用户的导航菜单
     *
     * @return 树形列表
     */
    @Path("getMenuDataList")
    @POST
    @Operation(summary = "获取当前用户的导航菜单", tags = CUSTOM_SERVICE)
    public List<MenuData> getMenuDataList() {
        UserDto currentUser = user.getUserByIdThroughJDBC(UserDto.builder().id(RequestContext.getCorpLoginId()).build());
        String roleIds = currentUser.getRole_ids();
        if (StringUtils.isEmpty(roleIds)) {
            throw new BizException("角色ID列表 以逗号分隔 不能为空");
        }
        List<String> roleIdList = Arrays.asList(roleIds.split(","));

        // 根据角色id查询角色资源
        SingleResponse<BOList> roleResourceBOList = BoServiceUtils.findListByIn(ModelConst.T_ROLE_RESOURCE, "role_id", roleIdList);
        log.info("------------------------根据角色id查询角色资源列表数据：{}------------------------", JSONObject.toJSONString(roleResourceBOList));

        // 获取资源id列表
        List<String> resourceIdList = roleResourceBOList.getData().getData().stream()
                .map(roleResource -> String.valueOf(roleResource.get("resource")))
                .distinct()
                .collect(Collectors.toList());

        // 根据资源id列表查询资源列表数据
        SingleResponse<BOList> resourceBOList = BoServiceUtils.findListByIn(ModelConst.T_RESOURCE, "id", resourceIdList);
        log.info("------------------------根据资源id列表查询资源列表数据：{}------------------------", JSONObject.toJSONString(resourceBOList));
        List<ResourceDto> resourceList = ObjectMapperUtils.readValue(ObjectMapperUtils.toJSONString(resourceBOList.getData().getData()), ResourceDto.class);

        // 根据应用名称进行分组、排序
        Map<String, List<ResourceDto>> resourceMapGroupByAppCode = resourceList.stream()
                .sorted(Comparator.comparing(ResourceDto::getSort))
                .collect(Collectors.groupingBy(ResourceDto::getAppCode, LinkedHashMap::new, Collectors.toList()));
        Set<String> appCodeSet = resourceMapGroupByAppCode.keySet();
        List<MenuData> menuDataList = Lists.newArrayList();

        // 应用循环赋值
        List<ResourceDto> resourceListGroupByAppCode;
        List<ResourceDto> resourceListDistinctPageCode;
        SingleResponse<BOList> resourceBOListByAppCodeAndType;
        SingleResponse<BO> resourceBO;
        String[] columns = new String[]{"appCode", "type"};
        Operator[] operators = new Operator[]{Operator.EQ, Operator.EQ};
        Object[] columnsVal = new Object[2];
        columnsVal[1] = ResourceTypeEnum.APP.getCode();
        for (String appCode : appCodeSet) {
            columnsVal[0] = appCode;
            resourceListGroupByAppCode = resourceMapGroupByAppCode.get(appCode);

            // 获取应用名称
            resourceBOListByAppCodeAndType = BoServiceUtils.findListByComplex(ModelConst.T_RESOURCE, columns, columnsVal, operators);
            MenuData menuData = new MenuData();
            menuData.setTopName(String.valueOf(resourceBOListByAppCodeAndType.getData().getData().get(0).get("name")));

            // 根据页面编码进行去重
            resourceListDistinctPageCode = resourceListGroupByAppCode.stream()
                    .filter(resource -> Objects.nonNull(resource.getPageCode()) && ResourceTypeEnum.TABS.getCode().equals(resource.getType()))
                    .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(ResourceDto::getPageCode))), ArrayList::new));
            List<MenuData> childMenuDataList = Lists.newArrayList();

            // 设置应用菜单
            for (ResourceDto resource : resourceListDistinctPageCode) {
                // 获取菜单名称
                resourceBO = BoServiceUtils.loadBo(resource.getParent_id(), ModelConst.T_RESOURCE);
                // fixme 正常情况下父菜单都是有的，如果因为本地调测版本问题，修改了元数据，导致菜单为空，不显示该菜单，避免空指针错误
                if (resourceBO.getData().getData() == null || resourceBO.getData().getData().size() == 0) {
                    continue;
                }
                log.info("=======================resourceBO：{}，resource：{}=============================", resourceBO, resource);
                MenuData childMenuData = new MenuData();
                childMenuData.setSortKey(((BigDecimal) resourceBO.getData().getData().get("sortKey")).intValue());
                String menuName = String.valueOf(resourceBO.getData().getData().get("name"));
                childMenuData.setChildName(menuName);
                // 跨应用菜单，进行特殊处理
                if (AppConst.ORDER_CENTER.equals(appCode)) {
                    if ("代购合同管理".equals(menuName)) {
                        childMenuData.setAppCode(AppConst.DAIGOU);
                    } else if ("寄售发货通知".equals(menuName) || "寄售库存管理".equals(menuName) || "寄售消耗统计".equals(menuName)) {
                        childMenuData.setAppCode(AppConst.JISHOU);
                    } else if ("转采管理".equals(menuName)) {
                        childMenuData.setAppCode(AppConst.ZHUANCAI);
                    } else {
                        childMenuData.setAppCode(appCode);
                    }
                } else if (AppConst.FINANCIALCENTER.equals(appCode)) {
                    if ("转采财务".equals(menuName)) {
                        childMenuData.setAppCode(AppConst.ZHUANCAI);
                    } else {
                        childMenuData.setAppCode(appCode);
                    }
                } else {
                    childMenuData.setAppCode(appCode);
                }
                childMenuData.setPageCode(resource.getPageCode());
                childMenuDataList.add(childMenuData);
            }

            // 如果是固买市场应用，判断有没有固买市场菜单。固买市场绑定的页面和其他页面结构不一样，需要做特殊处理
            if (AppConst.GM_MARKET.equals(appCode)) {
                Optional<ResourceDto> first = resourceListGroupByAppCode.stream()
                        .filter(resourceDto -> ResourceTypeEnum.MENU.getCode().equals(resourceDto.getType()) && "固买市场".equals(resourceDto.getName()))
                        .findFirst();
                if (first.isPresent()) {
                    MenuData childMenuData = new MenuData();
                    childMenuData.setSortKey(first.get().getSortKey());
                    childMenuData.setChildName(first.get().getName());
                    childMenuData.setAppCode(appCode);
                    childMenuData.setPageCode("home");
                    childMenuDataList.add(childMenuData);
                }
            }
            // 根据sortKey对菜单进行排序
            childMenuDataList.sort(Comparator.comparing(MenuData::getSortKey));
            menuData.setChildren(childMenuDataList);
            menuDataList.add(menuData);
        }
        return menuDataList;
    }
}
